package by.ins.life.simpleimpl;

import java.io.Serializable;
import java.util.List;

import org.apache.log4j.Logger;

import by.ins.life.IData;
import by.ins.life.INuclear;
import by.ins.life.ISet;
import by.ins.life.ISolver;
import by.ins.life.evolution.GoalItem;
import by.ins.life.impl.Data;
import by.ins.life.work.NuclearMatrixUtils;
import by.yativem.commons.utils.math.IMath;
import by.yativem.commons.utils.math.MathProvider;
import by.yativem.commons.utils.matrix.IMatrix;
import by.yativem.commons.utils.matrix.IMatrixHandler;



public class SimpleSolver<T> implements ISolver<T>, Serializable {

	private static final long serialVersionUID = 1L;
	private static final Logger log = Logger.getLogger(SimpleSolver.class);
	private IMath<T> math;
	private NuclearMatrixUtils<T> matrixUtils;
	

	@Override
	public IData<T> solve(ISet<T> set,
			IData<T> input) {
		
	//	math =  set.getMatrix().get(0, 0).getMath();
		
		IMatrix<INuclear<T>> matrix = set.getMatrix(); 
		
		IData<T> result = new Data<T>();
		
		fillFirst(set, input);
		
		for (int i = 1 ;  i < matrix.getColumnsCount(); i++ ){
			
			final T  net = matrixUtils.getSum(matrix.getColumn(i-1));
			
			matrix.processColumn(i, new IMatrixHandler<INuclear<T>>() {

				@Override
				public void callBack(int row, int column, INuclear<T> nuclear) {
					if( math.compare( net, nuclear.getThreshold() ) >= 0   ){
						nuclear.setState(net);
					}else{
						nuclear.setState(math.getZero());
					}
				}
			});
			
		}
		
		List<INuclear<T>> mColumn =  matrix.getColumn(matrix.getColumnsCount()-1);
		for(int i =0 ; i < input.size();  i++){
			result.add(i, mColumn.get(i).getState() );
		}
		
		
		return result;
	}
	
	@SuppressWarnings("unchecked")
	public SimpleSolver(Class<?> clazz){
		
		this.math = (IMath<T>) MathProvider.getMathInstance(clazz);
		this.matrixUtils  = NuclearMatrixUtils.getInstanceFor(math);
	}
	
	protected void fillFirst( final ISet<T> set, IData<T> input){
		List<INuclear<T> > fColumn =
				set.getMatrix().getColumn(0);
		for( int i  =0; i < fColumn.size() ;i ++ ){			
			fColumn.get(i).setState( input.get(i));
		}		
	}	
	
	protected T inputSignal(){
		return null;
	}

	@Override
	public void solve(ISet<T> set, GoalItem<T> gi) {
		IData<T> decition = this.solve(set, gi.getInput());
		log.debug(decition);
		
		//throw new UnsupportedOperationException("Method is not implemented");
	}

	@Override
	public void solve(ISet<T> set, List<GoalItem<T>> gi) {
		// TODO Auto-generated method stub
		throw new UnsupportedOperationException("Method is not implemented");
	}
	
	

}
